﻿namespace Blaze.Editor
{
    using System.Collections;
    using System.Collections.Generic;

    /// <summary>
    /// 协同程序调度器。
    /// </summary>
    public class EditorCoroutineScheduler
    {
        public bool IsRunning
        {
            get { return mCoroutines.Count > 0; }
        }

        /// <summary>
        /// 同步执行协同程序。
        /// </summary>
        public static void Sync(IEnumerator fiber)
        {
            var node = new EditorCoroutine(fiber);
            node.Sync();
        }

        /// <summary>
        /// 同步执行协同程序。
        /// </summary>
        public static void Sync(IEnumerable enumerable)
        {
            var node = new EditorCoroutine(enumerable.GetEnumerator());
            node.Sync();
        }

        /// <summary>
        /// 启动一个新的协同程序。
        /// </summary>
        public EditorCoroutine Start(IEnumerator fiber)
        {
            var node = new EditorCoroutine(fiber);
            mCoroutines.AddFirst(node);
            return node;
        }

        /// <summary>
        /// 启动一个新的协同程序。
        /// </summary>
        public EditorCoroutine Start(IEnumerable enumerable)
        {
            var node = new EditorCoroutine(enumerable.GetEnumerator());
            mCoroutines.AddFirst(node);
            return node;
        }

        /// <summary>
        /// 停止所有的协同程序。
        /// </summary>
        public void Stop()
        {
            mCoroutines.Clear();
        }

        /// <summary>
        /// 调度。
        /// </summary>
        public void Tick()
        {
            var coroutine = mCoroutines.First;

            while (coroutine != null)
            {
                var next = coroutine.Next;

                if (coroutine.Value.IsStopping)
                    mCoroutines.Remove(coroutine);
                else if (!coroutine.Value.Next())
                    mCoroutines.Remove(coroutine);

                coroutine = next;
            }
        }

        private readonly LinkedList<EditorCoroutine> mCoroutines = new LinkedList<EditorCoroutine>();
    }
}